﻿using Idte.Core.Infrastructure.Repository;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;

//[assembly: demoReflection.Help("This Assembly demonstrates custom attributes creation and their run-time query.")]
namespace demoReflection
{
    public class MyContext : CodeFirstDbContext
    {
        public MyContext() : base(("DemoReflectionContext")) { }
    }
    class Program
    {
        [System.ComponentModel.DataAnnotations.DisplayAttribute(Name = "kaka")]
        //[ System.ComponentModel.DataAnnotations.Schema.ColumnAttribute]
        public int testpro { get; set; }

        static void Main(string[] args)
        {

            Console.WriteLine("Processing....");

           

            //Type att = Helper.TryGetType("System.ComponentModel.DataAnnotations.Schema.ColumnAttribute");
            //ConstructorInfo[] allCons = att.GetConstructors();

            createDLL();
            testDLL();
            
            //
            testCreateDB();


            //testAttr();
            //testParseXml();
            
            
            
            
            Console.WriteLine("Done! Press enter to exit.");
            Console.ReadLine();
            //DemoAutoGenerator.Model.Student
        }

        static void createDLL()
        {   //System.ComponentModel.DataAnnotations.KeyAttribute
            List<CustomAttributeInfo> attributesClass = new List<CustomAttributeInfo>();
            CustomAttributeInfo attrAggregate = new CustomAttributeInfo();
            attrAggregate.AttributeName = "Idte.Core.Infrastructure.Repository.AggregateAttribute";
            attributesClass.Add(attrAggregate);

            List<CustomAttributeInfo> attrProperties1 = new List<CustomAttributeInfo>();
            CustomAttributeInfo attrDisplay = new CustomAttributeInfo();
            attrDisplay.AttributeName = "System.ComponentModel.DataAnnotations.DisplayAttribute";
            attrDisplay.PropertiesInfos.Add(new CustomPropertyInfo(){Name = "Name",Value ="IdCard"});
            attrProperties1.Add(attrDisplay);
            
            List<CustomAttributeInfo> attrProperties2 = new List<CustomAttributeInfo>();
            CustomAttributeInfo attrForeignKey_Person = new CustomAttributeInfo();
            attrForeignKey_Person.AttributeName = "System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute";
            attrForeignKey_Person.ConstructorInfos.Add(new CustomPropertyInfo() { Name = "System.String", Value = "PersonId" });
            attrProperties2.Add(attrForeignKey_Person);
            

            List<CustomFieldInfo> module1_fields = new List<CustomFieldInfo>();
            CustomFieldInfo pro1 = new CustomFieldInfo();
            pro1.Name = "id";
            pro1.PrimaryType = "System.Int32";
            pro1.Attributes = attrProperties1;
            module1_fields.Add(pro1);
            

            CustomFieldInfo pro2 = new CustomFieldInfo();
            pro2.Name = "name";
            pro2.PrimaryType = "System.String";
            module1_fields.Add(pro2);

            CustomFieldInfo pro3 = new CustomFieldInfo();
            pro3.Name = "addressId";
            pro3.PrimaryType = "System.Int32";
            module1_fields.Add(pro3);

            CustomFieldInfo pro4 = new CustomFieldInfo();
            pro4.Name = "address";
            pro4.PrimaryType = "DemoAutoGenerator.Model.Address";//DemoAutoGenerator.Model.
            pro4.IsVirtualProperty = true;
            module1_fields.Add(pro4);

            CustomFieldInfo pro5 = new CustomFieldInfo();
            pro5.Name = "certificates";
            pro5.PrimaryType = "System.Collections.Generic.List`1";
            pro5.SecondaryTypes = new string[] { "DemoAutoGenerator.Model.Certificate" };
            pro5.IsVirtualProperty = true;
            module1_fields.Add(pro5);

            List<CustomFieldInfo> module2_fields = new List<CustomFieldInfo>();
            CustomFieldInfo pro9 = new CustomFieldInfo();
            pro9.Name = "id";
            pro9.PrimaryType = "System.Int32";
            module2_fields.Add(pro9);


            CustomFieldInfo pro10 = new CustomFieldInfo();
            pro10.Name = "country";
            pro10.PrimaryType = "System.String";
            module2_fields.Add(pro10);

            CustomFieldInfo pro11 = new CustomFieldInfo();
            pro11.Name = "district";
            pro11.PrimaryType = "System.String";
            module2_fields.Add(pro11);

            CustomFieldInfo pro12 = new CustomFieldInfo();
            pro12.Name = "street";
            pro12.PrimaryType = "System.String";//System.Collections.Generic.List`1
            module2_fields.Add(pro12);



            List<CustomFieldInfo> module3_fields = new List<CustomFieldInfo>();
            CustomFieldInfo pro20 = new CustomFieldInfo();
            pro20.Name = "id";
            pro20.PrimaryType = "System.Int32";
            pro20.Attributes = attrProperties1;
            module3_fields.Add(pro20);


            CustomFieldInfo pro21 = new CustomFieldInfo();
            pro21.Name = "name";
            pro21.PrimaryType = "System.String";
            module3_fields.Add(pro21);

            CustomFieldInfo pro22 = new CustomFieldInfo();
            pro22.Name = "school";
            pro22.PrimaryType = "System.String";
            module3_fields.Add(pro22);

            CustomFieldInfo pro23 = new CustomFieldInfo();
            pro23.Name = "personId";
            pro23.PrimaryType = "System.Int32";//"DemoAutoGenerator.Model.Person";//DemoAutoGenerator.Model.
            module3_fields.Add(pro23);

            CustomFieldInfo pro24 = new CustomFieldInfo();
            pro24.Name = "person";
            pro24.PrimaryType = "DemoAutoGenerator.Model.Person";
            pro24.Attributes = attrProperties2;
            module3_fields.Add(pro24);

            AutoGenerateAssembly demoDll = new AutoGenerateAssembly("DemoAutoGenerator");
            AutoGenerateType person = new AutoGenerateType("DemoAutoGenerator.Model.Person", module1_fields, attributesClass);
            AutoGenerateType student = new AutoGenerateType("DemoAutoGenerator.Model.Student", null, attributesClass);
            student.Parent = "DemoAutoGenerator.Model.Person";
            AutoGenerateType address = new AutoGenerateType("DemoAutoGenerator.Model.Address", module2_fields, attributesClass);
            AutoGenerateType certificate = new AutoGenerateType("DemoAutoGenerator.Model.Certificate", module3_fields, attributesClass);

            demoDll.AddType(person);
            demoDll.AddType(student);
            demoDll.AddType(address);
            demoDll.AddType(certificate);

            //demoDll.AddModule(module1);
            //demoDll.AddModule(module2);
            demoDll.BuildAssembly();
            demoDll.SaveAssembly();
        }
        static void testDLL() {
            string pathExe = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            Assembly testAssembly = Assembly.LoadFile(pathExe + "/DemoAutoGenerator.dll");
            Type[] modules = testAssembly.GetTypes();
            for (int m = 0; m < modules.Length; m++)
            {
                Console.WriteLine("className: {0}",modules[m].Name);
                PropertyInfo[] props = modules[m].GetProperties();

                for (int i = 0; i < props.Length; i++)
                {
                    Console.Write("propName: {0}, ", props[i].Name);
                    Attribute[] propAttrs = props[i].GetCustomAttributes().ToArray();
                    Console.WriteLine("\tattrs of prop:{0}", propAttrs.Length);
                    if (propAttrs.Length > 0)
                    {
                        for (int j = 0; j < propAttrs.Length; j++)
                        {
                            Console.WriteLine("\t\t{0}", propAttrs[i].ToString());
                        }
                        
                    }
                }
                Console.WriteLine("----------------------------------------------");
            }
            
            //MyClass1 myInstance = Activator.CreateInstance(myType) as MyClass1;
            //PropertyInfo numberPropertyInfo = myType.GetProperty("Mark");
            //numberPropertyInfo.SetValue(myInstance, 10.8);
            ////myInstance.number = 1;
            //int value = (int)numberPropertyInfo.GetValue(myInstance, null);
            //Console.WriteLine("value of {0}", value);
        }
        static void testAttr()
        {
            HelpAttribute HelpAttr;

            //Querying Assembly Attributes
            String assemblyName;
            Process p = Process.GetCurrentProcess();
            assemblyName = p.ProcessName + ".exe";

            Assembly a = Assembly.LoadFrom(assemblyName);


            foreach (Attribute attr in a.GetCustomAttributes(true))
            {
                HelpAttr = attr as HelpAttribute;
                if (null != HelpAttr)
                {
                    Console.WriteLine("Description of {0}:\n{1}",
                                      assemblyName, HelpAttr.Description);
                }
            }
        }
        static void testParseXml()
        {
            TypeManager.GetTypeCollection();
        
        }
        static void testCreateDB()
        {
            //MyContext ctx = new MyContext();
            //ctx.Set<DemoAutoGenerator.Model.Person>();
            //ctx.Set<DemoAutoGenerator.Model.Address>();
            //ctx.Set<DemoAutoGenerator.Model.Certificate>();
            //Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>());
            //DemoAutoGenerator.Model.Address addr = new DemoAutoGenerator.Model.Address() { Country = "Viet Nam", District = "District 1", Street = "Nguyen Cong Tru" };
            //List<DemoAutoGenerator.Model.Certificate> certificates = new List<DemoAutoGenerator.Model.Certificate>();
            //DemoAutoGenerator.Model.Certificate ctf1 = new DemoAutoGenerator.Model.Certificate() { Name = "ctf1", School = "HCMUS" };
            //DemoAutoGenerator.Model.Certificate ctf2 = new DemoAutoGenerator.Model.Certificate() { Name = "ctf2", School = "RMIT" };
            //certificates.Add(ctf1);
            //certificates.Add(ctf2);
            //DemoAutoGenerator.Model.Person person = new DemoAutoGenerator.Model.Person() { Name = "Idte", Address = addr, Certificates = certificates };


            //ctx.Set<DemoAutoGenerator.Model.Person>().Add(person);
            //ctx.SaveChanges();
           

            

        }
    }
}    
